﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using UnityEngine;


// Translate: Finished
// Debug: 

namespace Assets.Scripts.LDS
{
	class SceneSemGraphManager
	{


		private List<SceneSemGraph> m_sceneSemGraphs= new List<SceneSemGraph> ();
		private string m_mainSceneDBFolderPath;
		private SortedSet<string> m_modelBlackList = new SortedSet<string> ();  // list of models that is irregular and need to be blacked
		public SceneSemGraphManager()
		{
			loadGraphs();
			loadModelBlackList();
		}
		public void loadGraphs() // Load data from Database
		{
			string currLine;
			using (StreamReader sr = new StreamReader(Params.ssgList_pth))//Change to my_ scene_ list_ release.txt Using front data set
			{
				currLine = sr.ReadLine();
				if (currLine.Contains("SceneNum"))
				{
					int sceneNum = Util.StringToIntegerList(currLine, "SceneNum ")[0];
					m_sceneSemGraphs.Clear();


					System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
					stopwatch.Start(); //  Start monitoring code runtime

					List<string> allSSGFileNames = new List<string>();

					// load all file names
					for (int i = 0; i < sceneNum; i++)
					{
						currLine = sr.ReadLine();

						string ssgFileName =  Params.ssg_pth + currLine + ".ssg";//Change to my_ SSGs use the front data set
						allSSGFileNames.Add(ssgFileName);
					}

					//#pragma omp parallel for
					for (int i = 0; i < sceneNum; i++)
					{
						SceneSemGraph newSceneSemGraph = new SceneSemGraph(allSSGFileNames[i]);
						newSceneSemGraph.m_dbSSGId = i;
						newSceneSemGraph.SetInPlace();
						m_sceneSemGraphs.Add(newSceneSemGraph);
						
						TextDialog.textDebug(allSSGFileNames[i] + "loaded successful!");
					}


					stopwatch.Stop(); //  Stop monitoring
					TimeSpan timespan = stopwatch.Elapsed; //  Gets the total time measured by the current instance
					TextDialog.textDebug(sceneNum + " graphs loaded in " + timespan.TotalSeconds + " s\n");
                }
				m_ssgNum = m_sceneSemGraphs.Count;

			}

		}
		public SceneSemGraph getGraph(int id) { return m_sceneSemGraphs[id]; }
		public int m_ssgNum;
		public void loadModelBlackList()
		{
			string currLine;
			using (StreamReader sr = new StreamReader(Params.relationModelPath + "model_blacklist.txt"))
			{
				while (sr.Peek()!=-1)
				{
					currLine = sr.ReadLine();
					List<string> parts = new List<string>(currLine.Split(','));
					m_modelBlackList.Add(parts[0]);
				}
			}

		}
		public bool isModelInBlackList(string s)
		{
			if (m_modelBlackList.Contains(s))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		public MetaModel retrieveForModelInstance(string catName, List<string> attriNames)
		{
			List<(int, int)> exactMatchMdIds = new List<(int, int)>();
			List<(int, int)> otherCandiMdIds = new List<(int, int)>();

			for (int i = 0; i < this.m_ssgNum; i++)
			{
				SceneSemGraph currDBSSG = this.getGraph(i);

				for (int qNi = 0; qNi < currDBSSG.m_nodeNum; qNi++)
				{
					SemNode sgNode = currDBSSG.m_nodes[qNi];
					if (sgNode.nodeType == "object" && sgNode.nodeName == catName)
					{
						int modelId = currDBSSG.m_graphNodeToModelListIdMap[qNi];
						MetaModel md = currDBSSG.m_graphMetaScene.m_metaModellList[modelId];

						// test front dir for book to filter stand book
						Vector3 vec3 = new Vector3(0, 0, 1);
						if (catName == "book" && Vector3.Dot(md.frontDir, vec3) < 0.5)
						{
							continue;
						}

						// debug
						if (md.catName == "desk")
						{
							// 5ce562e0632b7e81d8e3889d90601dd1					
							// 6d67f92d6e11f29e5792b99b8245d225
							//if (md.name == "6d67f92d6e11f29e5792b99b8245d225")
							//{
							//	return md;
							//}
						}

						if (md.catName == "bed")
						{
							// 5ce562e0632b7e81d8e3889d90601dd1					
							// 6d67f92d6e11f29e5792b99b8245d225
							if (md.name == "b32ad01b13c6739daaddabe471cbd38e")
							{
								return md;
							}
						}

						if (md.catName == "monitor")
						{
							if (md.name == "241b26438e8523ee2846fa729d90e125")
							{
								return md;
							}
						}

						if (md.catName == "computermouse")
						{
							if (md.name == "90490d506c40f6b344ebbc705ad8c07")
							{
								return md;
							}
						}

						if (md.catName == "chair")
						{
							// b6f10c040560d6e41f6a5b0146bf3030
							// 1308f3ff2e55eae4f1783a44a88d6274
							//if (md.name == "1308f3ff2e55eae4f1783a44a88d6274")
							//{
							//	return md;
							//}
						}

						if (md.catName == "table")
						{
							//if (md.name == "97ac69442e657fcd7a968eef090b6698")
							//{
							//	return md;
							//}
						}

						if (!isModelInBlackList(md.name))
						{
							// collect attri names for current node
							List<string> currAttriNames = currDBSSG.getAttriNamesForNode(qNi);

							// match attributes
							int mAttriNum = 0;
							for (int t = 0; t < attriNames.Count; t++)
							{
								if (currAttriNames.Contains(attriNames[t]) == true)
								{
									mAttriNum++;
								}
							}

							if (mAttriNum == attriNames.Count)
							{
								exactMatchMdIds.Add((i, modelId));  // (graphId, modelId)
							}
							else
							{
								otherCandiMdIds.Add((i, modelId));
							}
						}
					}
				}
			}

			if (exactMatchMdIds.Count != 0)
			{
				int randId = Util.GenRandomInt(0, exactMatchMdIds.Count);
				(int, int) selectPair = (exactMatchMdIds[randId]);

				SceneSemGraph currDBSSG = this.getGraph(selectPair.Item1);
				return currDBSSG.m_graphMetaScene.m_metaModellList[selectPair.Item2];
			}
			else if (otherCandiMdIds.Count != 0)
			{
				int randId = Util.GenRandomInt(0, otherCandiMdIds.Count);
				(int, int) selectPair = otherCandiMdIds[randId];

				SceneSemGraph currDBSSG = this.getGraph(selectPair.Item1);
				return currDBSSG.m_graphMetaScene.m_metaModellList[selectPair.Item2];
			}
			else
			{
				// Failure case: return a room for debug
				return new MetaModel();
			}
		}

		public void Clear()
        {
			foreach(var i in m_sceneSemGraphs)
            {
				i.reset();
            }
        }
	}
}

